#include "D3dStdafx.h"
#include "Rhw.h"
#include "OgreD3D9Texture.h"
#include "OgreD3D9RenderSystem.h"
#include "d3d9.h"
#include "d3dx9.h"
#include "DxErr.h"

using namespace Ogre;
CRhw::CRhw(void)
{
	// 
}

CRhw::~CRhw(void)
{

}

struct DXUT_SCREEN_VERTEX_UNTEX {
	FLOAT x, y, z;
	FLOAT rhw;
	DWORD color;
	FLOAT tu, tv;   // Texture coordinates
};

// Custom flexible vertex format (FVF) describing the custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)


void CRhw::Render()
{

	Ogre::D3D9RenderSystem* renderSystem = static_cast<Ogre::D3D9RenderSystem*>(Ogre::Root::getSingleton().getRenderSystem());
	IDirect3DDevice9 * pd3dDevice = NULL;
	pd3dDevice = Ogre::D3D9RenderSystem::getActiveD3D9Device();
	renderSystem->_beginFrame();
	pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
	pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
	pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
	pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_ADD );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_ADD );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
	pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );

	pd3dDevice->SetVertexShader( NULL );
	pd3dDevice->SetPixelShader( NULL );
	pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
	RenderInfo * info;

	for (RenderInfoMap::iterator i  = m_RenderInfoMap.begin();i!= m_RenderInfoMap.end();++i)
	{
		info = &i->second;
		if (info->bisVisible)
		{
			renderSystem->_setTexture( 0, true, info->_TexturePtr );
			DXUT_SCREEN_VERTEX_UNTEX vertices[4] =
			{
				( float )info->_x - info->_width/2, ( float )info->_y - info->_height/2,	0.5f, 1.0f, info->_colorTopLeft,     0.0f, 0.0f,
				( float )info->_x + info->_width/2,	( float )info->_y - info->_height/2,	0.5f, 1.0f, info->_colorTopRight,    1.0f, 0.0f,
				( float )info->_x + info->_width/2, ( float )info->_y + info->_height/2,	0.5f, 1.0f, info->_colorBottomRight, 1.0f, 1.0f,
				( float )info->_x - info->_width/2, ( float )info->_y + info->_height/2,	0.5f, 1.0f, info->_colorBottomLeft,  0.0f, 1.0f,
			};
			HRESULT  hr = pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof( DXUT_SCREEN_VERTEX_UNTEX ) );
			if (FAILED( hr ))
			{
				String msg = DXGetErrorDescription(hr);
				OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to DrawPrimitiveUP : " + msg, "CRhw::Render()" );
			}
		}
	}
	renderSystem->_endFrame();
}

void	CRhw::SetTexture(const char *key,const char *textName)
{
	RenderInfo * infoo;
	infoo = GetRenderInfo(key) ;
	if (!infoo)
	{
		return;
	}

	infoo->_TexturePtr = Ogre::TextureManager::getSingleton().getByName(textName);

}

void		CRhw::setVisible(const char *key,bool visible)
{
	RenderInfo * infoo;
	infoo = GetRenderInfo(key) ;
	if (!infoo)
	{
		return;
	}
	infoo->bisVisible = visible;
}

void		CRhw::addRenderInfo(const char *key)
{
	RenderInfo info;
	m_RenderInfoMap[key] = info;
}
void		CRhw::deleteRenderInfo(const char *key)
{
	RenderInfoMap::iterator i  = 
		m_RenderInfoMap.find(key);
	if (i != m_RenderInfoMap.end())
	{
		m_RenderInfoMap.erase(i);
	}
}

void		CRhw::setPosition(const char *key,int x ,int y)
{
	RenderInfo * info;
	info = GetRenderInfo(key) ;
	if (!info)
	{
		return;
	}
	info->_x = x;info->_y = y; 
}
void        CRhw::SetSize(const char *key, int width, int height )
{
	RenderInfo * info;
	info = GetRenderInfo(key) ;
	if (!info)
	{
		return;
	}
	info->_width = width; info->_height = height; //UpdateRects();
}

RenderInfo * CRhw::GetRenderInfo(const char *key) 
{
	RenderInfoMap::iterator i = m_RenderInfoMap.find(key);
	if (i != m_RenderInfoMap.end())
	{
		return &i->second;
	}
	return NULL;
}